#include "dirsblocks.h"
#include "params.hpp"
#include "qpainter.h"
#include "data.h"
#include <qcolor.h>
#include <qfont.h>
#include <qframe.h>
#include <qnamespace.h>
#include <qpoint.h>
#include <qwidget.h>
#include <string>

static QColor colors[] = {
  QColor(74, 69, 230),   // 0, white
  QColor(0, 105, 52),    // 1, up, green
  QColor(212, 92, 40),   // 2, dn, red
  QColor(0, 163, 81),    // 3, up-zero
  QColor(212, 122, 70),  // 4, dn-zero
  QColor(0, 237, 118),   // 5, up-swing
  QColor(255, 204, 153), // 6, dn-swing
  QColor(180, 60, 200),  // 7, swing
  QColor(32, 32, 32)     // 8, background
};

static QColor
dirToColor(const DIR_TYPE d) noexcept
{
  QColor clr;
  switch (d) {
    case 1:
      clr = colors[1];
      break;
    case -1:
      clr = colors[2];
      break;
    default:
      clr = colors[0];
      break;
  }

  return clr;
}

static const int n_block_row = 7;
static const int x_margin = 4;
static const int y_margin = 5;
static const int text_top_margin = 2;
static const int new_w = 150;
static const int left_margin = 88;
static const int top_margin = 8;
static const int h = 25;
static const int w = (new_w - (n_block_row - 1) * x_margin) / n_block_row;

DirsBlocks::DirsBlocks(DataChart* chart)
  : QGraphicsItem(chart)
  , m_chart(chart)
{
  // Qt::PenStyle penStyle = Qt::PenStyle(Qt::PenStyle::SolidLine);
  // Qt::PenCapStyle cap = Qt::PenCapStyle(Qt::PenCapStyle::FlatCap);
  // Qt::PenJoinStyle join = Qt::PenJoinStyle(Qt::PenJoinStyle::RoundJoin);

  pen = QPen(colors[8]);
  brush = QBrush(Qt::blue, Qt::BrushStyle(Qt::BrushStyle::SolidPattern));

  imgPet[0].load("images/tom-up.png");
  imgPet[1].load("images/jerry-up.png");
  imgPet[2].load("images/mickey-up.png");
}

void
DirsBlocks::paint(QPainter* painter,
                  const QStyleOptionGraphicsItem* option,
                  QWidget* widget)
{
  Q_UNUSED(option);
  Q_UNUSED(widget);

  const auto p = Trade::get_vo_by_index(g_dp.vo, g_dp.vo_size, g_dp.m_posIndex);
  if (!p)
    return;

  draw_blocks(painter, p);

  draw_opportunities(painter, p);

  if (sos.b_show_tom && g_pets.pet[0].dir)
    draw_image_(painter, 0);
  if (sos.b_show_jerry && g_pets.pet[1].dir)
    draw_image_(painter, 1);
  if (sos.b_show_mickey && g_pets.pet[2].dir)
    draw_image_(painter, 2);
}

void
DirsBlocks::draw_blocks(QPainter* painter, const Trade::Params* p) noexcept
{
  int x = left_margin;
  int y = top_margin + y_margin;

  painter->setPen(pen);
  painter->setRenderHint(QPainter::Antialiasing, true);

  // for (int8_t i = 0; i < amount_rect; ++i, y += (h + y_margen)) {
  //   QRect rect(x, y, x + w, y + h);

  //   if (i % 2)
  //     brush.setColor(QColor("red"));
  //   else
  //     brush.setColor(QColor("green"));

  //   painter->setBrush(brush);
  //   painter->drawRect(rect);
  // }

  const auto ddt_turn_space =
    p->dd3_sd.retrive_dir_type(p->dir_turns_space, p->t_now_);
  const auto dir_first_turn = p->ttttt.get_first_dir_type();
  const auto dir_solved_near = p->nft.d_near;
  const auto dir_solved_far = p->nft.d_far;
  const auto dir_near_10 = p->flv_79.d_near_10;
  const auto dir_near_rt = p->flv_79.d_near_rt;
  const auto dir_far_10 = p->flv_79.d_far_10;
  const auto dir_far_rt = p->flv_79.d_far_rt;
  const auto ddt_vision = p->retrive_vision_dir_type();
  const auto dir_pre_vision = p->pre_vision;

  QRect qrect(x, y, w, h);
  brush.setColor(colors[ddt_vision]);
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  qrect = QRect(x, y, w, h);
  brush.setColor(
    colors[p->dd3_exp.retrive_dir_type(p->dir_explicit, p->t_now_)]);
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  qrect = QRect(x, y, w, h);
  brush.setColor(colors[ddt_turn_space]);
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  qrect = QRect(x, y, w, h);
  brush.setColor(colors[dir_first_turn]);
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  qrect = QRect(x, y, w, h);
  brush.setColor(dirToColor(dir_solved_near));
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  qrect = QRect(x, y, w, h);
  brush.setColor(dirToColor(dir_solved_far));
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  qrect = QRect(x, y, w, h);
  brush.setColor(dirToColor(p->dirs.big_dir));
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  // Row 2
  x = left_margin;
  y += h + y_margin;

  // g_dirs.ddt_force
  qrect = QRect(x, y, w, h);
  brush.setColor(colors[p->ddt_force]);
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  qrect = QRect(x, y, w, h);
  brush.setColor(dirToColor(dir_near_10));
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  qrect = QRect(x, y, w, h);
  brush.setColor(dirToColor(dir_near_rt));
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  qrect = QRect(x, y, w, h);
  brush.setColor(dirToColor(dir_far_10));
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  qrect = QRect(x, y, w, h);
  brush.setColor(dirToColor(dir_far_rt));
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  qrect = QRect(x, y, w, h);
  brush.setColor(dirToColor(dir_pre_vision));
  painter->setBrush(brush);
  painter->drawRect(qrect);
  x += (w + x_margin);

  qrect = QRect(x, y, w, h);
  brush.setColor(dirToColor(p->get_mda_dir()));
  painter->setBrush(brush);
  painter->drawRect(qrect);
}

void
DirsBlocks::draw_opportunities(QPainter* painter,
                               const Trade::Params* p) noexcept
{
  auto font = painter->font();
  font.setBold(false);
  font.setPixelSize(w);
  painter->setFont(font);

  pen.setColor(colors[3]);
  painter->setPen(pen);

  int x = left_margin + x_margin;
  auto textw = w + w + y_margin;
  int y = top_margin + h + h + y_margin + y_margin + y_margin + text_top_margin;
  QString inString = std::to_string(p->oppor_trend.trend_up).c_str();
  // pen.setColor(colors[8]);
  // painter->setPen(pen);
  QRect qrect = QRect(x, y, textw, h);
  // painter->drawText(qrect.adjusted(0, 2, 2, 0), inString);
  pen.setColor(colors[3]);
  painter->setPen(pen);
  painter->drawText(qrect, inString);

  x += textw;
  inString = std::to_string(p->oppor_trend.force_up).c_str();
  qrect = QRect(x, y, textw, h);
  painter->drawText(qrect, inString);

  x += textw;
  inString = std::to_string(p->oppor_trend.vision_up).c_str();
  qrect = QRect(x, y, textw, h);
  painter->drawText(qrect, inString);


  // x += textw;
  // inString = std::to_string(p->oppor_trend.oppor_up).c_str();
  // qrect = QRect(x, y, textw, h);
  // painter->drawText(qrect, inString);

  x = left_margin + x_margin;
  y += h;
  inString = std::to_string(p->oppor_trend.trend_dn).c_str();
  // pen.setColor(colors[8]);
  // painter->setPen(pen);
  qrect = QRect(x, y, textw, h);
  // painter->drawText(qrect.adjusted(0, 2, 2, 0), inString);
  pen.setColor(colors[4]);
  painter->setPen(pen);
  painter->drawText(qrect, inString);

  x += textw;
  inString = std::to_string(p->oppor_trend.force_dn).c_str();
  qrect = QRect(x, y, textw, h);
  painter->drawText(qrect, inString);

  x += textw;
  inString = std::to_string(p->oppor_trend.vision_dn).c_str();
  qrect = QRect(x, y, textw, h);
  painter->drawText(qrect, inString);

  // x += textw;
  // inString = std::to_string(p->oppor_trend.oppor_dn).c_str();
  // qrect = QRect(x, y, textw, h);
  // painter->drawText(qrect, inString);

  font.setBold(true);
  font.setPixelSize(w + w);
  painter->setFont(font);
  pen.setColor((p->dir_opportunity > 0) ? colors[3] : colors[4]);
  painter->setPen(pen);

  x = left_margin + x_margin + x_margin + new_w;
  textw = w + w + w + y_margin;
  y = top_margin + y_margin + text_top_margin;
  qrect = QRect(x, y, textw, h + h + y_margin);
  inString = std::to_string(std::abs(p->pct_oppo)).c_str();
  painter->drawText(qrect.adjusted(0, 2, 2, 0), inString);

  font.setBold(true);
  font.setPixelSize(w + w);
  painter->setFont(font);
  pen.setColor((p->dir_opportunity > 0) ? colors[3] : colors[4]);
  painter->setPen(pen);

  x = left_margin + x_margin + x_margin + new_w;
  textw = w + w + w + y_margin;
  y = top_margin + y_margin + text_top_margin;
  qrect = QRect(x, y, textw, h + h + y_margin);
  inString = std::to_string(std::abs(p->pct_oppo)).c_str();
  painter->drawText(qrect.adjusted(0, 2, 2, 0), inString);

  x += w + w + w + x_margin;
  font.setPixelSize(double(w) * 1.2);
  painter->setFont(font);
  textw = w + w + w + w + w + w + y_margin;
  qrect = QRect(x, y + 12, textw, h + h + y_margin);
  char buf[64];
  if (g_dp.reverse_sapace > 0) {
    snprintf(buf, 64, "%.01f", g_dp.reverse_sapace);
  } else {
    buf[0] = ' ';
    buf[1] = 0;
  }
  painter->drawText(qrect.adjusted(0, 2, 2, 0), buf);

  pen.setColor(colors[8]);
  painter->setPen(pen);
}

void
DirsBlocks::updateGeometry()
{
  prepareGeometryChange();
  setPos(m_chart->mapToPosition(QPointF(10, 10)));
}

void
DirsBlocks::draw_image_(QPainter* painter, const int idx_pet) noexcept
{
  auto pet = g_pets.pet + idx_pet;
  int x = g_dp.time_2_x(pet->tm);
  QPointF old(x, pet->hp);
  QPointF pnt = m_chart->mapToPosition(old);
  // printf("POINT: %.01f %.01f --> %.01f %.01f\n", qreal(x), pet->hp, pnt.x(),
  // pnt.y());
  const auto& img = imgPet[idx_pet];

#ifdef _LINUX_
  const int8_t pxx = 47;
#endif
#ifdef _MACOS_
  const int8_t pxx = 64;
#endif
#ifdef _WINDOWS_
  const int8_t pxx = 64;
#endif

  const int8_t pyy = 64;

  QRect qrect = {
    int(pnt.x()) - pxx + 8, int(pnt.y()) - ((pet->dir < 0) ? pyy : 0), pxx, pyy
  };

  if (pet->dir > 0) {
    painter->drawImage(qrect, img);
  } else {
    QTransform trans;
    QImage rotatedImg = img.transformed(trans.rotate(180, Qt::ZAxis));
    painter->drawImage(qrect, rotatedImg);
  }
}

QRectF
DirsBlocks::boundingRect() const
{
  QRectF rect(m_chart->rect());
  return rect;
}
